<?php namespace App\Models;

use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Watson\Validating\ValidatingTrait;
use Illuminate\Database\Eloquent\Model;
use App\Events\WorksCreatedEvent;
use Illuminate\Support\Facades\Cache;


/**
 * Class Works
 *
 * @package App\Models
 * @property int $id
 * @property int $entry_form_id 报名表id
 * @property int $user_id 用户id
 * @property int $award_id 奖项id
 * @property int $proposition_company_id 命题企业id
 * @property int $works_type_id 作品类别id
 * @property string $sn 作品编号
 * @property string $name 作品名称
 * @property string $idea 创意思想
 * @property int $num 系列数量
 * @property int $first_author_id 第一作者
 * @property int $status 状态
 * @property string $created_at
 * @property string $updated_at
 * @property string $deleted_at
 * @property int $form_file_id 报名表附件id
 * @property string $form_file 报名表附件key
 * @property int $uploads_order 上传序列号
 * @property int $uploads_count 上传序统计,冗余字段
 * @property int $is_verified 是否审核
 * @property string $thumb 缩略图
 * @property int $vote_award_id 获奖奖项
 * @property-read \App\Models\Award $award
 * @property-read \App\Models\PropositionCompany $propositionCompany
 * @property-read \App\Models\WorksType $worksType
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Author[] $authors
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Teacher[] $teachers
 * @property-read \App\Models\EntryForm $entryForm
 * @property-read \App\Models\User $user
 * @property-read \App\Models\Author $firstAuthor
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\WorksUpload[] $worksUploads
 * @property-read \App\Models\VoteAward $voteAward
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereId($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereSn($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereAwardId($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works wherePropositionCompanyId($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereWorksTypeId($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereUserId($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereName($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereIdea($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereNum($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereCreatedAt($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereUpdatedAt($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereDeletedAt($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereFirstAuthorId($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereStatus($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereEntryFormId($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereFormFileId($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereUploadsOrder($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereUploadsCount($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereFormFile($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereIsVerified($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereThumb($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereVoteAwardId($value)
 * @property boolean $is_hidden
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Works whereIsHidden($value)
 * @mixin \Eloquent
 */
class Works extends Model
{
    use SoftDeletes;
    //use ValidatingTrait;


    protected $table = 'works';

    protected $dates = ['deleted_at'];

    protected $fillable = [
        'award_id',
        'proposition_company_id',
        'works_type_id',
        'name',
        'idea',
        'num',
        'first_author_id',
        'uploads_order',
        'is_hidden',
    ];

    protected $rules = [
        'creating' => [
            'entry_form_id' => 'required|integer|min:1',
            'user_id' => 'required|integer|min:1',
            'award_id' => 'required|integer|min:1',
            'proposition_company_id' => 'required|integer|min:1',
            'works_type_id' => 'required|integer|min:1',
            'name' => 'required',
            'idea' => 'required',
        ],
        'updating' => [
            'name' => 'required',
            'idea' => 'required',
        ],
    ];

    protected $validationMessages = [
        'entry_form_id.required' => '报名表必选',
        'entry_form_id.min' => '报名表必选',
        'entry_form_id.integer' => '报名表id格式有误',
        'user_id.required' => '用户id必填',
        'user_id.min' => '用户id必填',
        'user_id.integer' => '用户id格式有误',
        'award_id.required' => '赛事必填',
        'award_id.min' => '赛事必填',
        'award_id.integer' => '赛事格式有误',
        'works_type_id.required' => '作品类别必填',
        'works_type_id.min' => '作品类别必填',
        'works_type_id.integer' => '作品类别格式有误',
        'proposition_company_id.required' => '命题企业必填',
        'proposition_company_id.min' => '命题企业必填',
        'proposition_company_id.integer' => '命题企业id格式有误',
        'first_author_id.required' => '第一作者必选',
        'first_author_id.min' => '第一作者必选',
        'first_author_id.integer' => '第一作者id格式有误',
        'name.required' => '名称必填',
        'idea.required' => '创意思想必填',
        'name.max' => '作品名称字数不得超过21个字符',
        //'num.required'                    => '作品数量系列必填',
    ];

    public static function getWorksListByUserId($user_id)
    {
        $result = Cache::remember('works-list:' . $user_id, 120, function () use ($user_id) {
            $worksIdsByAuthor = DB::table('works_author')->where('author_id', $user_id)->pluck('works_id')->toArray();
            $worksIdsByCreated = DB::table('works')->where('user_id', $user_id)->pluck('id')->toArray();
            $worksIds = array_merge($worksIdsByAuthor, $worksIdsByCreated);
            return $worksIds;
        });
        return $result;
    }

    /**
     * 赛事
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function award()
    {
        return $this->belongsTo('\App\Models\Award', 'award_id');
    }


    /**
     * 命题企业
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function propositionCompany()
    {
        return $this->belongsTo('\App\Models\PropositionCompany', 'proposition_company_id');
    }

    /**
     * 作品类别
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function worksType()
    {
        return $this->belongsTo('\App\Models\WorksType', 'works_type_id');
    }

    /**
     * 作者
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function authors()
    {
        return $this->belongsToMany(User::class, 'works_author', 'works_id', 'author_id')
            ->withPivot('sort')
            ->orderBy('sort', 'asc');
    }

    /**
     * WorksAuthor
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function worksAuthors()
    {
        return $this->hasMany(WorksAuthor::class, 'works_id', 'id');
    }

    /**
     * 指导教师
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function teachers()
    {
        return $this->belongsToMany(User::class, 'works_teacher', 'works_id', 'teacher_id')
            ->withPivot('sort')
            ->orderBy('sort', 'asc');
    }

    /**
     * 报名表
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function entryForm()
    {
        return $this->belongsTo('\App\Models\EntryForm', 'entry_form_id');
    }

    /**
     * 用户
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function user()
    {
        return $this->belongsTo('\App\Models\User', 'user_id');
    }

    /**
     * 第一作者
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function firstAuthor()
    {
        return $this->belongsTo('\App\Models\Author', 'first_author_id');
    }

    /**
     * 生成序列号
     * @return string
     */
    public function generateSn()
    {
        try {
            if (!$this->sn) {
                $this->sn = $this->award->code . '-' . $this->worksType->code
                    . str_pad($this->propositionCompany->code, 2, '0', STR_PAD_LEFT) . date('Y')
                    . str_pad($this->id, 6, '0', STR_PAD_LEFT);
                $this->save();
            }
            return $this->sn;
        } catch (\Exception $e) {
            \Log::critical('生成作品序列号出错', ['error' => $e->getMessage()]);
            return '出错';
        }
    }


    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function reports()
    {
        return $this->hasMany('\App\Models\Report', 'works_id')->orderBy('is_sure', 'asc');
    }

    public function getNewReportsCount()
    {
        return Report::where(['works_id' => $this->id, 'is_sure' => 0])->count();
    }

    /**
     * 附件
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function worksUploads()
    {
        return $this->hasMany('\App\Models\WorksUpload', 'works_id');
    }

    public function getUploads()
    {
        $uploads = [];
        $fengmian = WorksUpload::where(['works_id' => $this->id, 'type' => '封面'])->first();
        if ($fengmian) {
            $uploads[] = $fengmian;
        }
        $mulus = WorksUpload::where(['works_id' => $this->id, 'type' => '目录'])->orderBy('sort', 'asc')->get();
        if ($mulus) {
            foreach ($mulus as $mulu) {
                $uploads[] = $mulu;
            }
        }
        $neirongs = WorksUpload::where(['works_id' => $this->id, 'type' => '内容'])->orderBy('sort', 'asc')->get();
        if ($neirongs) {
            foreach ($neirongs as $neirong) {
                $uploads[] = $neirong;
            }
        }
        $fengdi = WorksUpload::where(['works_id' => $this->id, 'type' => '封底'])->first();
        if ($fengdi) {
            $uploads[] = $fengdi;
        }
        return $uploads;
    }

    public function worksTexts()
    {
        return $this->hasOne('\App\Models\WorksText', 'works_id');
    }

    /**
     * 检查状态
     *
     * public function checkStatus()
     * {
     * $currentStatus = $this->status;
     * if ($this->worksUploads()->count() > 0) {
     * $this->status = 1;
     * } else {
     * $this->status = 0;
     * }
     *
     * if ($this->status != $currentStatus) {
     * $this->save();
     * }
     * }*/

    /**
     * 下一个上传序号
     * @param int $length
     * @return int|string
     */
    public function generateNextUploadOrder($length = 2)
    {
        $this->uploads_order += 1;
        $b = $length - strlen($this->uploads_order);
        $i = $this->uploads_order;
        for ($c = 1; $c <= $b; $c++) {
            $i = '0' . $i;
        }
        return $i;
    }

    /**
     * 上传报名表附件
     * @param UploadedFile $file
     */
    public function uploadFormFile(UploadedFile $file)
    {
        $uploadFileTypes = ['image/png', 'image/jpg', 'image/jpeg',];
        $uploadFileExtensions = ['png', 'jpg', 'jpeg'];
        //校验文件类型
        if (!in_array($file->getMimeType(), $uploadFileTypes) ||
            !in_array(strtolower($file->getClientOriginalExtension()), $uploadFileExtensions)
        ) {
            throw new FileException('文件类型有误,只允许上传png,jpg,jpeg');
        }

        $this->form_file = $this->generateSn() . '.' . strtolower($file->getClientOriginalExtension());
        if (!\Storage::disk('form_file')->put($this->form_file, \File::get($file))) {
            throw new FileException('保存文件失败.');
        } else {
            $this->save();
        }
    }

    /**
     * 获取报名表附件url
     * @return string
     */
    public function getFormFileUrl()
    {
        if ($this->form_file) {
            return config('filesystems.disks.form_file.url_prefix') . $this->form_file;
        } else {
            return '';
        }
    }

    /**
     * 获奖奖项
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function voteAward()
    {
        return $this->belongsTo('\App\Models\VoteAward', 'vote_award_id');
    }

    /**
     * 获取缩略图
     * @return string
     */
    public function getThumbUrl()
    {
        try {
            if ($this->thumb) {
                return $this->thumb;
            } elseif ($url = $this->generateThumb()) {
                return $url;
            } else {
                return url('assets/thumb/none.png');
            }
        } catch (\Exception $e) {
            \Log::error('生成作品缩略图出错,' . $e->getMessage(), $this->toArray());
        }
    }


    /**
     * 生成缩略图
     * @return string
     */
    public function generateThumb()
    {
        try {
            if ($this->worksType->templet == 3) {
                $thumbUrl = url('assets/thumb/wenan.png');
            } elseif ($this->worksType->templet == 4) {
                $cehua = WorksUpload::where(['works_id' => $this->id, 'type' => '封面'])->first();
                $thumbUrl = $cehua->getRateThumbUrl();
            } else {
                if ($this->worksUploads->count() > 0) {
                    $upload = $this->worksUploads->first();
                    switch (strtolower($upload->extension)) {
                        case "avi":
                            $thumbUrl = $upload->getVideoThumbUrl();
                            break;
                        case "doc":
                            $thumbUrl = url('assets/thumb/doc.png');
                            break;
                        case "docx":
                            $thumbUrl = url('assets/thumb/docx.png');
                            break;
                        case "flv":
                            $thumbUrl = $upload->getVideoThumbUrl();
                            break;
                        case "mp3":
                            $thumbUrl = url('assets/thumb/mp3.png');
                            break;
                        case "mp4":
                            $thumbUrl = $upload->getVideoThumbUrl();
                            break;
                        case "pdf":
                            $thumbUrl = url('assets/thumb/pdf.png');
                            break;
                        case "swf":
                            $thumbUrl = url('assets/thumb/swf.png');
                            break;
                        case "tiff":
                            $thumbUrl = url('assets/thumb/tiff.png');
                            break;
                        case "url":
                            $thumbUrl = url('assets/thumb/url.png');
                            break;
                        case "wmv":
                            $thumbUrl = $upload->getVideoThumbUrl();
                            break;
                        default:
                            $thumbUrl = $upload->getRateThumbUrl();
                            break;
                    }
                }
            }
            $this->thumb = $thumbUrl;
            $this->save();
            $url = $this->thumb;
            return $url;
        } catch (\Exception $e) {
            \Log::error('生成作品缩略图出错,' . $e->getMessage(), $this->toArray());
        }
    }

    /**
     * 保存到碱法投票表
     * @return static
     */
    public function saveToJianfaVote()
    {
        $this->generateThumb();
        return JianfaVote::create($this->toArray());
    }

    /**
     * 打包附件
     * @return bool|string
     */
    public function packUploads()
    {
        if ($this->worksUploads->count() > 0) {
            $zipFilePath = "uploads/works_export/{$this->sn}.zip";
            $zipper = \Zipper::make(public_path($zipFilePath));
            foreach ($this->worksUploads as $worksUploads) {
                if ($worksUploads->extension == 'url') {
                    $zipper->addString("{$worksUploads->id}_url.txt", $worksUploads->key);
                } elseif ($worksUploads->extension == 'idea') {
                    $zipper->addString("{$worksUploads->id}_idea.txt", $worksUploads->key);
                } else {
                    $zipper->addString($worksUploads->filename, \Storage::disk($worksUploads->disk)->get($worksUploads->key));
                }
            }
            $zipper->close();
            return $zipFilePath;
        } else {
            throw new \Exception('该作品还没有附件。');
        }
    }

    /**
     * 获取文案类作品内容
     * @return App\Models\WorksText
     */
    public function worksText()
    {
        return $this->hasOne('worksType', 'works_id', 'id');
    }

    /**
     * 获取 上传文件 路径
     * 用于区分上传文件
     * @return string
     */
    public function getFileUploadPath()
    {
        return $this->award->code . '/' . str_pad($this->propositionCompany->code . '/' . $this->worksType->code, 2, '0', STR_PAD_LEFT) .
            '/' . $this->sn;
    }

    /**
     *
     * @return string
     */
    public function getSNCodeFileName()
    {
        return $this->sn . '-qrcode.png';
    }


    public function getWorksAwardSearchName()
    {
        $searchAwardSetting = DB::table('xyj_works_award_search_setting')->where('award_id', $this->award_id)->select('voteAward_id')->pluck('voteAward_id');
        if (in_array($this->vote_award_id, $searchAwardSetting)) {
            return $this->voteAward->name;
        } else {
            return '未获奖';
        }
    }


    protected static function boot()
    {
        parent::boot();
        self::created(function ($model) {
            \Event::fire(new WorksCreatedEvent($model));
        });
    }


}



